package cn.com.anysdk.redis.demo.controller;

import cn.com.anysdk.redis.api.IRedisService;
import cn.com.anysdk.starter.config.redis.RedisProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;

import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * Redis连接诊断控制器
 * 用于诊断Redis连接问题
 */
@RestController
@RequestMapping("/api/redis/diagnostic")
public class RedisDiagnosticController {

    @Autowired
    private IRedisService redisService;

    @Autowired
    private RedisProperties redisProperties;

    /**
     * 全面的Redis连接诊断
     */
    @GetMapping("/full")
    public Map<String, Object> fullDiagnostic() {
        Map<String, Object> result = new HashMap<>();
        result.put("timestamp", System.currentTimeMillis());

        // 1. 配置检查
        result.put("config", checkConfig());

        // 2. 网络连接检查
        result.put("network", checkNetwork());

        // 3. Redis服务检查
        result.put("redis", checkRedisService());

        // 4. 连接池检查
        result.put("pool", checkConnectionPool());

        return result;
    }

    /**
     * 检查配置
     */
    private Map<String, Object> checkConfig() {
        Map<String, Object> config = new HashMap<>();

        try {
            String env = redisProperties.getEnvironment();
            config.put("environment", env);

            if ("local".equals(env)) {
                RedisProperties.LocalConfig local = redisProperties.getLocal();
                config.put("host", local.getHost());
                config.put("port", local.getPort());
                config.put("database", local.getDatabase());
                config.put("hasPassword", local.getPassword() != null && !local.getPassword().isEmpty());
            }

            config.put("status", "OK");
        } catch (Exception e) {
            config.put("status", "ERROR");
            config.put("error", e.getMessage());
        }

        return config;
    }

    /**
     * 检查网络连接
     */
    private Map<String, Object> checkNetwork() {
        Map<String, Object> network = new HashMap<>();

        try {
            String host = redisProperties.getLocal().getHost();
            int port = redisProperties.getLocal().getPort();

            // 尝试TCP连接
            long startTime = System.currentTimeMillis();
            try (Socket socket = new Socket(host, port)) {
                long connectTime = System.currentTimeMillis() - startTime;
                network.put("tcpConnection", "SUCCESS");
                network.put("connectTime", connectTime + "ms");
                network.put("host", host);
                network.put("port", port);
            }
        } catch (Exception e) {
            network.put("tcpConnection", "FAILED");
            network.put("error", e.getMessage());
            network.put("suggestion", "请检查Redis服务是否启动，端口是否正确");
        }

        return network;
    }

    /**
     * 检查Redis服务
     */
    private Map<String, Object> checkRedisService() {
        Map<String, Object> redis = new HashMap<>();

        try {
            // 尝试直接连接Redis
            String host = redisProperties.getLocal().getHost();
            int port = redisProperties.getLocal().getPort();
            String password = redisProperties.getLocal().getPassword();

            try (Jedis jedis = new Jedis(host, port)) {
                if (password != null && !password.isEmpty()) {
                    jedis.auth(password);
                }

                // 测试ping
                String pong = jedis.ping();
                redis.put("ping", pong);
                redis.put("status", "CONNECTED");

                // 获取Redis信息
                String info = jedis.info("server");
                String[] lines = info.split("\r\n");
                for (String line : lines) {
                    if (line.startsWith("redis_version:")) {
                        redis.put("version", line.split(":")[1]);
                        break;
                    }
                }

            }
        } catch (Exception e) {
            redis.put("status", "FAILED");
            redis.put("error", e.getMessage());

            // 提供具体的错误建议
            String errorMsg = e.getMessage().toLowerCase();
            if (errorMsg.contains("connection refused")) {
                redis.put("suggestion", "Redis服务未启动，请运行: redis-server");
            } else if (errorMsg.contains("timeout")) {
                redis.put("suggestion", "连接超时，请检查网络和防火墙设置");
            } else if (errorMsg.contains("auth")) {
                redis.put("suggestion", "认证失败，请检查密码配置");
            } else {
                redis.put("suggestion", "请检查Redis服务状态和配置");
            }
        }

        return redis;
    }

    /**
     * 检查连接池
     */
    private Map<String, Object> checkConnectionPool() {
        Map<String, Object> pool = new HashMap<>();

        try {
            // 尝试通过服务获取连接
            boolean pingResult = redisService.ping();
            pool.put("serviceConnection", pingResult ? "SUCCESS" : "FAILED");

            // 连接池配置信息
            pool.put("poolConfig", getPoolConfigInfo());

        } catch (Exception e) {
            pool.put("serviceConnection", "FAILED");
            pool.put("error", e.getMessage());

            // 分析错误类型
            String errorMsg = e.getMessage().toLowerCase();
            if (errorMsg.contains("unexpected end of stream")) {
                pool.put("analysis", "连接被意外关闭，通常是Redis服务未启动或网络问题");
                pool.put("solution", "1. 检查Redis服务状态\n2. 检查网络连接\n3. 重启应用");
            }
        }

        return pool;
    }

    /**
     * 获取连接池配置信息
     */
    private Map<String, Object> getPoolConfigInfo() {
        Map<String, Object> poolInfo = new HashMap<>();

        try {
            RedisProperties.LocalConfig local = redisProperties.getLocal();
            RedisProperties.PoolConfig poolConfig = local.getPool();

            poolInfo.put("maxTotal", poolConfig.getMaxTotal());
            poolInfo.put("maxIdle", poolConfig.getMaxIdle());
            poolInfo.put("minIdle", poolConfig.getMinIdle());
            poolInfo.put("testOnBorrow", poolConfig.isTestOnBorrow());
            poolInfo.put("testOnReturn", poolConfig.isTestOnReturn());
            poolInfo.put("testWhileIdle", poolConfig.isTestWhileIdle());

        } catch (Exception e) {
            poolInfo.put("error", "无法获取连接池配置: " + e.getMessage());
        }

        return poolInfo;
    }

    /**
     * 快速连接测试
     */
    @GetMapping("/quick")
    public Map<String, Object> quickTest() {
        Map<String, Object> result = new HashMap<>();
        result.put("timestamp", System.currentTimeMillis());

        try {
            boolean connected = redisService.ping();
            result.put("connected", connected);
            result.put("status", connected ? "SUCCESS" : "FAILED");
            result.put("message", connected ? "Redis连接正常" : "Redis连接失败");
        } catch (Exception e) {
            result.put("connected", false);
            result.put("status", "ERROR");
            result.put("message", "连接异常: " + e.getMessage());
            result.put("error", e.getClass().getSimpleName());
        }

        return result;
    }
}